package yl.hs.bmipfull.service.production.impl;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yl.hs.bmipfull.daos.material.IRawMaterialInventoryDao;
import yl.hs.bmipfull.daos.production.IProductionLineDao;
import yl.hs.bmipfull.daos.production.IProductionRecordDao;
import yl.hs.bmipfull.daos.production.IProductionRecordDetailsDao;
import yl.hs.bmipfull.pojo.material.RawMaterialCateEntity;
import yl.hs.bmipfull.pojo.material.RawMaterialInfoEntity;
import yl.hs.bmipfull.pojo.material.WarehouseEntity;
import yl.hs.bmipfull.pojo.production.ProductionRecordDetailsEntity;
import yl.hs.bmipfull.pojo.production.ProductionRecordEntity;
import yl.hs.bmipfull.service.material.IRMWarehouseService;
import yl.hs.bmipfull.service.material.IRawMaterialCateService;
import yl.hs.bmipfull.service.material.IRawMaterialInfoService;
import yl.hs.bmipfull.service.production.IProductionRecordService;
import yl.hs.bmipfull.utils.Tl;
import yl.hs.bmipfull.utils.datastate.ActionType;
import yl.hs.bmipfull.viewmodels.PageQuery;
import yl.hs.bmipfull.viewmodels.PageResult;
import yl.hs.bmipfull.viewmodels.production.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 张凯
 * @apiNote 生产记录表服务层接口实现
 * @since 2021年10月25日 15时53分41秒 <br/>
 */
@Service
public class ProductionRecordServiceImpl extends ProductionBaseService implements IProductionRecordService {



    @Override
    public List<ProductionRecordEntity> queryList(PageQuery pageQuery) throws Exception {
        return queryList(pageQuery, "");
    }

    @Override
    public List<ProductionRecordEntity> queryList(PageQuery pageQuery,String productCateSn) throws Exception {
        pageQuery.checkSortSides(ProductionRecordEntity.class);
        return dao.queryPage(pageQuery.getQuery(),productCateSn);
    }

    @Override
    public PageResult<ProductionRecordEntity> queryPage(PageQuery pageQuery, int rowNum, int page) throws Exception {
        pageQuery.checkSortSides(ProductionRecordEntity.class);
        pageQuery.getQuery().put("querySkip", (page - 1) * rowNum);
        pageQuery.getQuery().put("pageSize", rowNum);
        PageResult<ProductionRecordEntity> result = new PageResult<>(rowNum);
        result.setRecords(dao.queryCountByCondition(pageQuery.getQuery()));
        result.setPage(page);
        result.setData(queryList(pageQuery));
        return result;
    }

    @Override
    public PageResult<ProductionRecordVO> queryPageVO(PageQuery pageQuery, int rowNum, int page) throws Exception {
        pageQuery.checkSortSides(ProductionRecordEntity.class);
        pageQuery.getQuery().put("querySkip", (page - 1) * rowNum);
        pageQuery.getQuery().put("pageSize", rowNum);
        PageResult<ProductionRecordVO> result = new PageResult<>(rowNum);
        result.setRecords(dao.queryCountByCondition(pageQuery.getQuery()));
        result.setPage(page);
        List<ProductionRecordEntity> recordList = queryList(pageQuery);
        List<ProductionRecordVO> productionRecordVoList =new ArrayList<>();
        recordList.forEach(t->{
            ProductionRecordVO recordVO = new ProductionRecordVO();
            BeanUtils.copyProperties(t, recordVO);
            List<ProductionRecordDetailsEntity> recordDetailsList = recordDetailsDao.queryListByRecordId(t.getId());
            List<ProductionRecordDetailsVO> detailsVOList = new ArrayList<>();
            recordDetailsList.forEach(d -> {
                ProductionRecordDetailsVO detailsVO = new ProductionRecordDetailsVO();
                try {
                    BeanUtils.copyProperties(d, detailsVO);
                    RawMaterialInfoEntity materialInfo = materialInfoService.findBySn(d.getRawMaterialSn());
                    RawMaterialCateEntity materialCateEntity = materialCateService.findBySn(materialInfo.getRmCateSN());
                    detailsVO.setRmCateName(materialCateEntity.getCateName());
                    detailsVO.setRmName(materialInfo.getRmName());
                    detailsVO.setRmSpec(materialInfo.getRmSpec());
                    WarehouseEntity warehouseEntity = warehouseService.findBySn(d.getWarehouseSn());
                    if (warehouseEntity!= null) {
                        detailsVO.setRmWarehouseName(warehouseEntity.getWhName());
                    }
                    detailsVO.setSingleConfigRatioQuantity(
                            recordVO.getActualOutput() == null? BigDecimal.ZERO:
                                    detailsVO.getConfigRatioQuantity()
                                            .divide(recordVO.getActualOutput(),3, RoundingMode.HALF_UP));
                    detailsVO.setSingleConsumptionQuantity(
                            recordVO.getActualOutput() == null? BigDecimal.ZERO:
                                    detailsVO.getConsumptionQuantity()
                                            .divide(recordVO.getActualOutput(),3, RoundingMode.HALF_UP));
                    detailsVO.setSingleDifferenceQuantity(
                            recordVO.getActualOutput() == null? BigDecimal.ZERO:
                                    detailsVO.getDifferenceQuantity()
                                            .divide(recordVO.getActualOutput(),3, RoundingMode.HALF_UP));
                } catch (Exception ex){
                    System.out.println(ex.getMessage());
                }
                detailsVOList.add(detailsVO);
            });
            recordVO.setDetails(detailsVOList);
            productionRecordVoList.add(recordVO);
        });
        result.setData(productionRecordVoList);
        return result;
    }


    @Override
    public ProductionRecordEntity findBySn(String sn) {
        return dao.findBySN(sn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer saveProductionRecord(Map<String, Object> model, String sn) throws Exception {
        Integer result;
        ProductionRecordEntity entity;
        if (Tl.isEmpty(sn)) {
            //执行保存
            entity = new ProductionRecordEntity();
            Tl.getChangeLog(entity, model);
            entity.setPYFieldValue();
            result = dao.insertNew(entity);
            if (result > 0) {
                writeLog(ActionType.CREATE, entity.getTaskSn(), "插入生产记录表信息", Tl.toJson(entity), ProductionRecordEntity.class);
            }

        } else {
            //执行修改
            entity = findBySn(sn);
            Tl.getChangeLog(entity, model);
            entity.setPYFieldValue();
            result = dao.update(entity);
            if (result > 0) {
                writeLog(ActionType.UPDATE, sn, "更新生产记录表信息", Tl.toJson(entity), ProductionRecordEntity.class);
            }
        }

        return result;
    }


    @Override
    public List<ProductionRecordDetailsEntity> queryDetailsList(PageQuery pageQuery, String productCateSn) {
        pageQuery.checkSortSides(ProductionRecordEntity.class);
        return dao.queryDetailPage(pageQuery.getQuery(),productCateSn);
    }

    @Override
    public Integer deleteRecordMax() {
        var lineList=productionLineDao.getAll();
        int result=0;
        for (var line: lineList ) {
            if(dao.getCountByLineSN(line.getSn())>0){
                var recordId = dao.getRecordMaxId(line.getSn());
                var recordDetails=recordDetailsDao.FindMaxByRecordId(recordId,line.getSn());
                for (var detail:recordDetails) {
                    if(detail.getConsumptionQuantity().compareTo(BigDecimal.ZERO)!=0 ) {
                        var wareHouse=rawMaterialInventoryDao.findByWHSNAndRmSN(detail.getWarehouseSn(), detail.getRawMaterialSn());
                        if(wareHouse!=null){
                            wareHouse.setQuantity(wareHouse.getQuantity().add(detail.getConsumptionQuantity().divide(BigDecimal.valueOf(1000), RoundingMode.FLOOR)));
                            rawMaterialInventoryDao.update(wareHouse);
                            var cangKu=warehouseService.findBySn(wareHouse.getWhSN());
                            cangKu.setInventory(cangKu.getInventory().add(detail.getConsumptionQuantity().divide(BigDecimal.valueOf(1000), RoundingMode.FLOOR)));
                            warehouseService.update(cangKu);
                        }
                    }
                }
                recordDetailsDao.deleteMaxRecordDetails(recordId,line.getSn());
                result+=dao.deleteRecordMax(recordId,line.getSn());
            }

        }
        return result;
    }

    @Override
    public Map<String, Object> queryProductionRecordByHouse() {
        var  instance = Calendar.getInstance();
        instance.setTime(new Date());
        instance.set(Calendar.SECOND, 0);
        instance.set(Calendar.MINUTE, 0);
        instance.set(Calendar.HOUR_OF_DAY, 0);
        instance.set(Calendar.MILLISECOND, 0);
        var nowStart=instance.getTime();
        instance.add(Calendar.DATE,1);
        var nowEnd=instance.getTime();
        var nowdata =  dao.queryProductionRecordByHouse(nowStart,nowEnd);
        instance.add(Calendar.DATE,-2);
        var lastdata =  dao.queryProductionRecordByHouse(instance.getTime(),nowStart);
        Map<String,Object> result = new HashMap<>();
        result.put("newdata",Wanshan(nowdata));
        result.put("lastdata",Wanshan(lastdata));
        return result;
    }

    @Override
    public Map<String, Object> queryProductionRecordByMonthon() {
        var  instance = Calendar.getInstance();
        instance.set(instance.get(Calendar.YEAR), Calendar.JANUARY,1);
        var startime=instance.getTime();
        instance.set(instance.get(Calendar.YEAR), Calendar.DECEMBER,31);
        var endtime = instance.getTime();
        var nowdata =  dao.queryProductionRecordByMonthon(startime,endtime);
        instance.set(instance.get(Calendar.YEAR)-1, Calendar.JANUARY,1);
        var startimes = instance.getTime();
        instance.set(instance.get(Calendar.YEAR), Calendar.DECEMBER,31);
        var endtimes = instance.getTime();
        var lastdata =  dao.queryProductionRecordByMonthon(startimes,endtimes);
        Map<String,Object> result = new HashMap<>();
        result.put("newdata",Wanshan2(nowdata));
        result.put("lastdata",Wanshan2(lastdata));
        return result;
    }

    @Override
    public PageInfo<ProductionRecordSModel> queryProductionRecordSModel(PageQuery pageQuery, int rowNum, int page) {
        pageQuery.checkSortSides(ProductionRecordEntity.class);
        PageHelper.startPage(page, rowNum);
        return new PageInfo<>(dao.queryProductionRecordSModel(pageQuery.getQuery()));
    }

    @Override
    public List<ProductionRecordDetailSO> queryByRecordId(List<Long> allId) {
        return recordDetailsDao.queryByRecordId(allId);
    }

    public List<ProductionRecordModel> Wanshan(List<ProductionRecordModel> data){
        var ss = data.stream().map(ProductionRecordModel::getNumber).collect(Collectors.toList());
        List<ProductionRecordModel> list = new ArrayList<>();
        for (var i=0;i<24;i++){
            if(!ss.contains(i)){
                list.add(new ProductionRecordModel(i,0,BigDecimal.valueOf(0)));
            }
        }
        data.addAll(list);
        return data.stream().sorted(Comparator.comparing(ProductionRecordModel::getNumber)).collect(Collectors.toList());
    }
    public List<ProductionRecordModel> Wanshan2(List<ProductionRecordModel> data){
        var ss = data.stream().map(ProductionRecordModel::getNumber).collect(Collectors.toList());
        List<ProductionRecordModel> list = new ArrayList<>();
        for (var i=1;i<13;i++){
            if(!ss.contains(i)){
                list.add(new ProductionRecordModel(i,0,BigDecimal.valueOf(0)));
            }
        }
        data.addAll(list);
        return data.stream().sorted(Comparator.comparing(ProductionRecordModel::getNumber)).collect(Collectors.toList());
    }

    @Autowired
    public void setDao(IProductionRecordDao dao) {
        this.dao = dao;
    }

    @Autowired
    public void setMaterialCateService(IRawMaterialCateService materialCateService) {
        this.materialCateService = materialCateService;
    }

    @Autowired
    public void setMaterialInfoService(IRawMaterialInfoService materialInfoService) {
        this.materialInfoService = materialInfoService;
    }

    @Autowired
    public void setRecordDetailsDao(IProductionRecordDetailsDao recordDetailsDao) {
        this.recordDetailsDao = recordDetailsDao;
    }

    @Autowired
    public void setWarehouseService(IRMWarehouseService warehouseService) {
        this.warehouseService = warehouseService;
    }

    private IProductionRecordDao dao;
    private IProductionRecordDetailsDao recordDetailsDao;
    private IRawMaterialInfoService materialInfoService;
    private IRawMaterialCateService materialCateService;
    private IRMWarehouseService warehouseService;
    @Autowired
    private IProductionLineDao productionLineDao;
    @Autowired
    private IRawMaterialInventoryDao rawMaterialInventoryDao;
}